﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Routing;
using AxeFrog.Composition;
using AxeFrog.Data;
using AxeFrog.Security;

namespace AxeFrog.Web
{
	public abstract class WebApplication : MefApplication
	{
		private readonly CatalogManager _catalogManager;
		private readonly string _dynamicPagesControllerName;

		protected CatalogManager Catalog
		{
			get { return _catalogManager; }
		}

#if DEBUG
		public string LoadedAssemblies { get; private set; }
#endif

		protected WebApplication(string dynamicPagesControllerName, params Assembly[] otherAssemblies)
			: this(dynamicPagesControllerName, Assembly.GetCallingAssembly())
		{
		}

		private WebApplication(string dynamicPagesControllerName, Assembly appAssembly, params Assembly[] otherAssemblies)
		{
			// Code for integrating controllers with MEF has been adapted from the sample and overview located
			// at http://blogs.msdn.com/hammett/archive/2009/04/23/mef-and-asp-net-mvc-sample.aspx

			_dynamicPagesControllerName = dynamicPagesControllerName;
			var assemblies = new List<Assembly>(otherAssemblies)
			{
				//typeof(WebApplication).Assembly, // AxeFrog.dll
				typeof(ContainerManager).Assembly, // AxeFrog.dll
				//typeof(User).Assembly, // AxeFrog.Security.dll
				appAssembly // AxeFrog.YourWebsite.dll
			};

#if DEBUG
			StringBuilder sb = new StringBuilder();
			foreach(var asm in assemblies)
				sb.AppendLine(new FileInfo(asm.Location).Name);
			LoadedAssemblies = sb.ToString();
#endif

			_catalogManager = new CatalogManager(assemblies.ToArray());

			BeginRequest += Application_BeginRequest;
			EndRequest += Application_EndRequest;
			Error += Application_Error;
		}

		protected WebApplication(params Assembly[] otherAssemblies)
			: this(null, Assembly.GetCallingAssembly(), otherAssemblies)
		{
		}

		protected virtual void Application_Error(object sender, EventArgs e)
		{
			
		}

		protected virtual void RegisterRoutes(RouteCollection routes, ContainerManager container)
		{
			routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
			routes.IgnoreRoute("{resource}.ico/{*pathInfo}");

			RegisterAllAreas();

			//routes.MapRoute("DefaultView",
			//                "{controller}/{id}",
			//                new { controller = "", action = "View", area = "Main", id = UrlParameter.Optional },
			//                new { id = "^[0-9]+$" }
			//);
			//routes.MapRoute("Default",
			//                "{controller}/{action}/{id}",
			//                new { controller = "Home", action = "Index", id = UrlParameter.Optional }
			//);
		}

		protected virtual void RegisterAllAreas()
		{
			AreaRegistration.RegisterAllAreas();
		}

		protected virtual void Application_Start()
		{
			ApplicationStartRan = true;
			var container = new ContainerManager(_catalogManager);

			// allows us to reference aspx/ascx files out of assemblies if necessary
			HostingEnvironment.RegisterVirtualPathProvider(new AssemblyResourceVirtualPathProvider());

			RegisterRoutes(RouteTable.Routes, container);

			ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(this));
		}

		void Application_BeginRequest(object sender, EventArgs e)
		{
			HttpContext.Current.Items[ContainerKey] = new ContainerManager(_catalogManager);
		}

		void Application_EndRequest(object sender, EventArgs e)
		{
			Container.Dispose();
		}

		private const string ContainerKey = "AxeFrog.Web.WebApplication.Container";
		public override ContainerManager Container
		{
			get { return HttpContext.Current.Items[ContainerKey] as ContainerManager; }
		}
		public Exception LastException { get; private set; }
		public bool ApplicationStartRan { get; private set; }
	}
}
